/*
 * 花样编辑窗口
 * 舞者无罪
 * 2014.11.21
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <minigui/common.h>
#include <minigui/minigui.h>
#include <minigui/gdi.h>
#include <minigui/window.h>
#include <minigui/control.h>
#include "resource.h"
#include "func.h"
#include "lang.h"
#include "flower.h"
#include "com.h"
#include "mhlabel.h"
#include "mhedit.h"
#include "mhbtn.h"
#include "dat.h"
#include "info.h"
#include "knit_line.h"
#include "utf8_gb2312.h"


#define LINE_CAPTION_LEFT           50
#define LINE_CAPTION_TOP            5
#define LINE_CAPTION_WIDTH          60
#define LINE_CAPTION_HEIGHT        20
#define POS_CAPTION_WIDTH           80
#define POS_CAPTION_HEIGHT          30

static void FlwToScreen(HWND hWnd, ushort *x, ushort *y);
/*
 *
 */
static void GetFlwRect(HWND hWnd, RECT *p)
{
    p->left = CX_EDGE_LEFT;
    p->right = CX_EDGE_LEFT + (CX_SCREEN - CX_EDGE_RIGHT - CX_EDGE_LEFT) /10 * 10 - 60;
    p->top = 30 + 5;
    p->bottom = (CY_SCREEN - 40) / 10 * 10 - 5 - 30;
}
/*
 *
 */
static void CreateFlowerInterface(HWND hWnd)
{
    int i = 0;
    char str[MH_FILE_NAME_MAX_LEN] = {0};
    //current line
    CreateWindow (MH_LABEL_NAME,
	   MW_LINE_FINISHED_CAPTION,
	   WS_CHILD | WS_VISIBLE | BS_LEFT,
	   IDC_STATIC,
	   LINE_CAPTION_LEFT,
	   LINE_CAPTION_TOP,
	   LINE_CAPTION_WIDTH,
	   LINE_CAPTION_HEIGHT,
	   hWnd, MH_LABEL_BKGND_BLACK | MH_LABEL_TEXT_CYAN);
    CreateWindow (MH_LABEL_NAME,
	   "1",
	   WS_CHILD | WS_VISIBLE,
	   IDC_EDIT_Y,
	   LINE_CAPTION_LEFT + LINE_CAPTION_WIDTH,
	   LINE_CAPTION_TOP,
	   LINE_CAPTION_WIDTH,
	   LINE_CAPTION_HEIGHT,
	   hWnd, MH_LABEL_COLOR_3GROUP);
    CreateWindow (MH_LABEL_NAME,
	   MW_CURRENT_COL_CAPTION,
	   WS_CHILD | WS_VISIBLE | BS_LEFT,
	   IDC_STATIC,
	   LINE_CAPTION_LEFT + LINE_CAPTION_WIDTH * 2,
	   LINE_CAPTION_TOP,
	   LINE_CAPTION_WIDTH,
	   LINE_CAPTION_HEIGHT,
	   hWnd, MH_LABEL_BKGND_BLACK | MH_LABEL_TEXT_CYAN);
    CreateWindow (MH_LABEL_NAME,
	   "1",
	   WS_CHILD | WS_VISIBLE,
	   IDC_EDIT_X,
	   LINE_CAPTION_LEFT + LINE_CAPTION_WIDTH * 3,
	   LINE_CAPTION_TOP,
	   LINE_CAPTION_WIDTH,
	   LINE_CAPTION_HEIGHT,
	   hWnd, MH_LABEL_COLOR_3GROUP);
    const char *name = GetKnitFileName(g_knit_data);
	UTF_8ToGB2312(str, name, strlen(name) + 1);
    CreateWindow (MH_LABEL_NAME,
	   str,
	   WS_CHILD | WS_VISIBLE,
	   IDC_EDIT_FILE_NAME,
	   LINE_CAPTION_LEFT + LINE_CAPTION_WIDTH * 6,
	   LINE_CAPTION_TOP,
	   LINE_CAPTION_WIDTH * 3,
	   LINE_CAPTION_HEIGHT,
	   hWnd, MH_LABEL_BKGND_BLACK | MH_LABEL_TEXT_CYAN);
    //button below
    const char *scc[9] = {
        MW_POS2_CAPTION,
        MW_START3_CAPTION,
        MW_END4_CAPTION,
        MW_LEFT5_CAPTION,
        MW_RIGHT6_CAPTION,
        MW_UP7_CAPTION,
        MW_DOWN8_CAPTION,
        MW_MODIFY9_CAPTION,
        GetString(711),
    };
    int id[9] = {
        ID_GOTO_LINE,
        ID_START_LINE,
        ID_STOP_LINE,
        ID_LEFT,
        ID_RGHT,
        ID_UP,
        ID_DOWN,
        ID_EDIT,
        ID_ZOOM,
    };
    for(i = 0; i < 9; ++i)
    {
        CreateWindow (MH_BTN_NAME,
	        scc[i],
	        WS_CHILD | WS_VISIBLE | BS_FLAT,
	        id[i],
	        13 + 86 * i,
	        565,
	        80,
	        30,
	        hWnd, MH_BTN_BKGND_BLACK | MH_BTN_TEXT_CYAN);
    }

    WND_EXTRA_DATA data;
    data.value = GetWindowAdditionalData(hWnd);
    char edit[12][64] = {{0}};
    strcat(edit[0], GetString(709));
    strcat(edit[2], "A");
    strcat(edit[5], "H");
    strcat(edit[8], GetString(54));
    strcat(edit[11], GetString(710));
    if(data.pwnd_flower)
    {
        sprintf(edit[1], "%u", data.pwnd_flower->cnt_info.height);
        GetCmdString(edit[3], data.pwnd_flower->cnt_info.act, FALSE);
        GetCodeString(edit[4], data.pwnd_flower->cnt_info.codeA);
        GetCmdString(edit[6], data.pwnd_flower->cnt_info.act, TRUE);
        GetCodeString(edit[7], data.pwnd_flower->cnt_info.codeH);
        GetYarnString(edit[9], data.pwnd_flower->cnt_info.yarn, TRUE);
        strcat(edit[10], data.pwnd_flower->cnt_info.height & 1 ? ">>>>>>" : "<<<<<<");
    }
    int left[12] = {
         10, 60, 100, 110, 160, 230, 240, 274, 314, 348, 448, 580,
    };
    int width[12] = {
         50, 40, 10, 50, 70, 10, 34, 40, 34, 100, 50, 210,
    };
    for(i = 0; i < 12; ++i)
    {
        CreateWindow(MH_LABEL_NAME,
            edit[i],
            WS_CHILD | WS_VISIBLE,
            IDC_LABEL1 + i,
            left[i],
            535,
            width[i],
            20,
            hWnd, MH_LABEL_BKGND_BLACK | MH_LABEL_TEXT_GREEN);
    }
    RECT rect;
    GetFlwRect(hWnd, &rect);
    const char *sc[5] = {
            "1", "2", "3", "4", "5",
    };
    for(i = 0; i < 5; ++i)
    {
        CreateWindow(MH_LABEL_NAME,
            sc[i],
            WS_CHILD | WS_VISIBLE,
            IDC_STATIC,
            rect.right + 15 + 10 * i,
            rect.top - 22,
            10,
            20,
            hWnd, MH_LABEL_BKGND_BLACK | MH_LABEL_TEXT_GREEN);
    }
}
/*
 *
 */
static void FlushCntInfo(HWND hWnd)
{
    WND_EXTRA_DATA data;
    data.value = GetWindowAdditionalData(hWnd);
    char edit[11][64] = {{0}};
    strcat(edit[0], GetString(709));
    strcat(edit[2], "A");
    strcat(edit[5], "H");
    strcat(edit[8], GetString(54));
    if(data.pwnd_flower)
    {
        GetCntInfo(&data.pwnd_flower->cnt_info, data.pwnd_flower->y + 1);

        sprintf(edit[1], "%u", data.pwnd_flower->cnt_info.height);
        GetCmdString(edit[3], data.pwnd_flower->cnt_info.act, FALSE);
        GetCodeString(edit[4], data.pwnd_flower->cnt_info.codeA);
        GetCmdString(edit[6], data.pwnd_flower->cnt_info.act, TRUE);
        GetCodeString(edit[7], data.pwnd_flower->cnt_info.codeH);
        GetYarnString(edit[9], data.pwnd_flower->cnt_info.yarn, TRUE);
        strcat(edit[10], data.pwnd_flower->cnt_info.height & 1 ? ">>>>>>" : "<<<<<<");
    }
    int i = 0;
    for(i = 0; i < 11; ++i)
    {
        HWND hTmp = GetDlgItem(hWnd, IDC_LABEL1 + i);
        SetWindowCaption(hTmp, edit[i]);
        InvalidateRect(hTmp, NULL, TRUE);
    }

            RECT rect;
            uchar code = 0;
            if(data.pwnd_flower)
            {
                ushort x = data.pwnd_flower->x;
                ushort y = data.pwnd_flower->y;
                code = GetFlowerCode(g_knit_data, x, y);
                FlwToScreen(hWnd, &x, &y);
                rect.left = x;
                rect.left = __max(0, rect.left);
                rect.right = x + data.pwnd_flower->zoom;
                rect.right = __min(rect.right, CX_SCREEN);
                rect.top = y - data.pwnd_flower->zoom;
                rect.top = __max(0, rect.top);
                rect.bottom = y;
                rect.bottom = __min(rect.bottom, CY_SCREEN);


                InvalidateRect(hWnd, &rect, TRUE);
                HDC hdc = GetClientDC(hWnd);
                int width = GET_RECT_WIDTH(rect);
                int height = GET_RECT_HEIGHT(rect);
                FillBoxWithBitmapPart(hdc, rect.left, rect.top, width, height,0, 0,&g_bmp[BMP_FLW_FCS], (code) *10, 0);
                ReleaseDC(hdc);
            }
}
/*
 *
 */
void SetFlowerDat(HWND hWnd, uchar code)
{
    WND_EXTRA_DATA data;
    data.value = GetWindowAdditionalData(hWnd);
    if(data.pwnd_flower)
    {
        SetFlowerCode(g_knit_data, data.pwnd_flower->x, data.pwnd_flower->y, code);
    }
}
/*
 *
 */
void SetFlowerChange(HWND hWnd, int change)
{
    WND_EXTRA_DATA data;
    data.value = GetWindowAdditionalData(hWnd);
    if(data.pwnd_flower)
    {
        data.pwnd_flower->change = change;
    }
}
/*
 * x: start from 1
 * y: start from 1
 * ret: x,y start from 0
 */
static void ScreenToFlw(HWND hWnd, ushort *x, ushort *y)
{
    ushort nFlwWidth = GetFlowerWidth(g_knit_data);
    ushort nFlwHeight = GetFlowerHeight(g_knit_data);
    if(!nFlwWidth || !nFlwHeight)
    {
        *x = 0;
        *y = 0;
    }
    else
    {
        RECT rect;
        GetFlwRect(hWnd, &rect);
        ushort nWidth = GET_RECT_WIDTH(rect);
        ushort nHeight = GET_RECT_HEIGHT(rect);
        WND_EXTRA_DATA data;
        data.value = GetWindowAdditionalData(hWnd);
        if(data.pwnd_flower->zoom == 1 && (nWidth < nFlwWidth || nHeight < nFlwHeight))
        {
            float zoom = __max(nFlwWidth / (float)nWidth, nFlwHeight / (float)nHeight);
            *x = (*x - rect.left) * zoom;
            *y = (rect.bottom - 1 - *y) * zoom;
        }
        else
        {
            *x = (*x - rect.left) / data.pwnd_flower->zoom;
            *x += data.pwnd_flower->l;
            *y = (rect.bottom - 1 - *y) / data.pwnd_flower->zoom;
            *y += data.pwnd_flower->b;
        }
        if(*y >= nFlwHeight)
        {
            *y = nFlwHeight - 1;
        }
        if(*x >= nFlwWidth)
        {
            *x = nFlwWidth - 1;
        }
    }
}
/*
 *
 */
static void FlwToScreen(HWND hWnd, ushort *x, ushort *y)
{
    RECT rect;
    GetFlwRect(hWnd, &rect);
    ushort nWidth = GET_RECT_WIDTH(rect);
    ushort nHeight = GET_RECT_HEIGHT(rect);
    WND_EXTRA_DATA data;
    data.value = GetWindowAdditionalData(hWnd);
    ushort nFlwWidth = GetFlowerWidth(g_knit_data);
    ushort nFlwHeight = GetFlowerHeight(g_knit_data);
    if(data.pwnd_flower)
    {
        *x -= data.pwnd_flower->l;
        *y -= data.pwnd_flower->b;
        if(data.pwnd_flower->zoom == 1 && (nWidth < nFlwWidth || nHeight < nFlwHeight))
        {
            float zoom = __max(nFlwWidth / (float)nWidth, nFlwHeight / (float)nHeight);
            *x /= zoom;
            *x += rect.left;
            *y /= zoom;
            *y = rect.bottom - *y;
        }
        else
        {
            *x *= data.pwnd_flower->zoom;
            *x += rect.left;
            *y *= data.pwnd_flower->zoom;
            *y = rect.bottom - *y;
        }
    }
}
/*
 *
 */
static void JumpToStartLine(HWND hWnd)
{
    WND_EXTRA_DATA data;
    data.value = GetWindowAdditionalData(hWnd);
    if(data.pwnd_flower)
    {
        if(data.pwnd_flower->y > 0)
        {
            data.pwnd_flower->y = 0;
            data.pwnd_flower->b = 0;
            char sc[32] = { 0 };
            sprintf(sc, "%u", data.pwnd_flower->y + 1);
            HWND hEditWnd = GetDlgItem(hWnd, IDC_EDIT_Y);
            if(hEditWnd > 0)
            {
                SetWindowCaption(hEditWnd, sc);
                InvalidateRect(hEditWnd, 0, TRUE);
            }
            RECT rect;
            GetFlwRect(hWnd, &rect);
            InvalidateRect(hWnd, &rect, TRUE);
            FlushCntInfo(hWnd);
        }
    }
}
/*
 *
 */
static void JumpToEndLine(HWND hWnd)
{
    WND_EXTRA_DATA data;
    data.value = GetWindowAdditionalData(hWnd);
    if(data.pwnd_flower)
    {
        RECT rect;
        GetFlwRect(hWnd, &rect);
        int num = GET_RECT_HEIGHT(rect) / data.pwnd_flower->zoom;
        ushort height = GetFlowerHeight(g_knit_data);
        if(data.pwnd_flower->y + 1 < height)
        {
            data.pwnd_flower->y = height - 1;
            char sc[32] = {0};
            sprintf(sc, "%u", data.pwnd_flower->y + 1);
            HWND hEditWnd = GetDlgItem(hWnd, IDC_EDIT_Y);
            if(hEditWnd > 0)
            {
                SetWindowCaption(hEditWnd, sc);
                InvalidateRect(hEditWnd, 0, TRUE);
            }
            if(num + data.pwnd_flower->b < data.pwnd_flower->y + 1)
            {
                data.pwnd_flower->b = data.pwnd_flower->y + 1 - num;
            }
            InvalidateRect(hWnd, &rect, TRUE);
            FlushCntInfo(hWnd);
        }
    }
}
/*
 *
 */
static void DecX(HWND hWnd, ushort n)
{
    FLOWER_WND *p = (FLOWER_WND*)GetWindowAdditionalData(hWnd);
    if(p)
    {
        if(p->x < n)
        {
            p->x = 0;
        }
        else
        {
            p->x -= n;
        }
        if(p->x < p->l)
        {
            p->l = p->x;
        }
    }
    char sc[32] = {0};
    sprintf(sc, "%u", p->x + 1);
    HWND hEditWnd = GetDlgItem(hWnd, IDC_EDIT_X);
    if(hEditWnd > 0)
    {
        SetWindowCaption(hEditWnd, sc);
        InvalidateRect(hEditWnd, 0, TRUE);
    }
    RECT rect;
    GetFlwRect(hWnd, &rect);
    InvalidateRect(hWnd, &rect, TRUE);
}
/*
 *
 */
static void AddX(HWND hWnd, ushort n)
{
    FLOWER_WND *p = (FLOWER_WND*)GetWindowAdditionalData(hWnd);
    RECT rect;
    GetFlwRect(hWnd, &rect);
    if(p)
    {
        int nFlwWidth = GetFlowerWidth(g_knit_data);
        if(p->x + n < nFlwWidth)
        {
            p->x += n;
        }
        else
        {
            p->x = nFlwWidth - 1;
        }
        int nWidth = GET_RECT_WIDTH(rect);
        int num = nWidth / p->zoom;
        if(p->l + num <= p->x)
        {
            p->l = p->x + 1 - num;
        }
    }
    char sc[32] = {0};
    sprintf(sc, "%u", p->x + 1);
    HWND hEditWnd = GetDlgItem(hWnd, IDC_EDIT_X);
    if(hEditWnd > 0)
    {
        SetWindowCaption(hEditWnd, sc);
        InvalidateRect(hEditWnd, 0, TRUE);
    }
    InvalidateRect(hWnd, &rect, TRUE);
}
/*
 *
 */
static void AddY(HWND hWnd, ushort n)
{
    WND_EXTRA_DATA data;
    data.value = GetWindowAdditionalData(hWnd);
    RECT rect;
    GetFlwRect(hWnd, &rect);
    if(data.pwnd_flower)
    {
        int nFlwHeight = GetFlowerHeight(g_knit_data);
        if(data.pwnd_flower->y + n < nFlwHeight)
        {
            data.pwnd_flower->y += n;
        }
        else
        {
            data.pwnd_flower->y = nFlwHeight - 1;
        }
        int num = GET_RECT_HEIGHT(rect) / data.pwnd_flower->zoom;
        if(data.pwnd_flower->b + num <= data.pwnd_flower->y)
        {
            data.pwnd_flower->b = data.pwnd_flower->y + 1 - num;
        }
    }
    char sc[32] = {0};
    sprintf(sc, "%u", data.pwnd_flower->y + 1);
    HWND hEditWnd = GetDlgItem(hWnd, IDC_EDIT_Y);
    if(hEditWnd > 0)
    {
        SetWindowCaption(hEditWnd, sc);
        InvalidateRect(hEditWnd, 0, TRUE);
    }
    InvalidateRect(hWnd, &rect, TRUE);
    FlushCntInfo(hWnd);
}
/*
 *
 */
static void DecY(HWND hWnd, ushort n)
{
    WND_EXTRA_DATA data;
    data.value = GetWindowAdditionalData(hWnd);
    if(data.pwnd_flower)
    {
        if(data.pwnd_flower->y < n)
        {
            data.pwnd_flower->y = 0;
        }
        else
        {
            data.pwnd_flower->y -= n;
        }
        if(data.pwnd_flower->y < data.pwnd_flower->b)
        {
            data.pwnd_flower->b = data.pwnd_flower->y;
        }
    }
    char sc[32] = {0};
    sprintf(sc, "%u", data.pwnd_flower->y + 1);
    HWND hEditWnd = GetDlgItem(hWnd, IDC_EDIT_Y);
    if(hEditWnd > 0)
    {
        SetWindowCaption(hEditWnd, sc);
        InvalidateRect(hEditWnd, 0, TRUE);
    }
    RECT rect;
    GetFlwRect(hWnd, &rect);
    InvalidateRect(hWnd, &rect, TRUE);
    FlushCntInfo(hWnd);
}
/*
 *
 */
static void OnZoom(HWND hWnd)
{
    WND_EXTRA_DATA data;
    data.value = GetWindowAdditionalData(hWnd);
    RECT rect;
    GetFlwRect(hWnd, &rect);
    if(data.pwnd_flower)
    {
        if(data.pwnd_flower->zoom == 1)
        {
            ushort nWidth = GET_RECT_WIDTH(rect);
            ushort nHeight = GET_RECT_HEIGHT(rect);
            data.pwnd_flower->zoom = 10;
            ushort x = nWidth / 10;
            ushort y = nHeight / 10;
            data.pwnd_flower->l = __max(0, data.pwnd_flower->x + 1 - x);
            data.pwnd_flower->b = __max(0, data.pwnd_flower->y + 1 - y);
        }
        else
        {
            data.pwnd_flower->zoom = 1;
            data.pwnd_flower->l = 0;
            data.pwnd_flower->b = 0;
        }
        InvalidateRect(hWnd, &rect, FALSE);
    }
}
/*
 *
 */
static void OnBtnCmd(HWND hWnd, int nID)
{
	switch(nID)
	{
	case ID_ESC:
	    {
	        WND_EXTRA_DATA data;
            data.value = GetWindowAdditionalData(hWnd);
            if(data.pwnd_flower)
            {
                if(data.pwnd_flower->change)
                {
                    char sc[MH_FILE_NAME_MAX_LEN + sizeof(KNIT_FILE_DIR) + sizeof(".con")] = {0};
                    strcat(sc, KNIT_FILE_DIR);
                    strcat(sc, GetKnitFileName(g_knit_data));
                    strcat(sc, ".dat");
                    int ret = WriteDatFile(sc, g_knit_data);
                    if(ret)
                    {
                        printf("Write flower Fail: %d\n", ret);
                        AddSysLog(g_knit_data, LOG_TYPE_FILE, ret);
                        AfxInfoBox(hWnd, GetString(390), GetString(473));
                    }
                    else
                    {
                        SetFlowerBoundary(g_knit_data);
                        SendControlData(g_knit_data);
                        SendFlowerData(g_knit_data);
                        MH_FILE_SYNC();
                    }
                }
            }
	    	PostMessage (hWnd, MSG_CLOSE, 0, 0);
	    }
		break;
	case ID_GOTO_LINE:
	    {
	        HWND hTmp = CreateKnitLineWindow(hWnd);
	        if(hTmp > 0)
	        {
	            SetWindowAdditionalData(hTmp, GetFlowerHeight(g_knit_data));
	        }
	    }
	    break;
	case ID_START_LINE:
	    {
	        JumpToStartLine(hWnd);
	    }
	    break;
	case ID_STOP_LINE:
	    {
	        JumpToEndLine(hWnd);
	    }
	    break;
	case ID_LEFT:
	    {
	        RECT rect;
	        GetFlwRect(hWnd, &rect);
	        WND_EXTRA_DATA data;
	        data.value = GetWindowAdditionalData(hWnd);
	        if(data.pwnd_flower)
	        {
	            ushort num = GET_RECT_WIDTH(rect) / data.pwnd_flower->zoom;
	            if(data.pwnd_flower->l < num)
	            {
	                data.pwnd_flower->l = 0;
	            }
	            else
	            {
	                data.pwnd_flower->l -= num;
	            }
	            if(data.pwnd_flower->x < num)
	            {
	                data.pwnd_flower->x = 0;
	            }
	            else
	            {
	                data.pwnd_flower->x -= num;
	            }
	            char sc[32] = { 0 };
                sprintf(sc, "%u", data.pwnd_flower->x + 1);
                HWND hEditWnd = GetDlgItem(hWnd, IDC_EDIT_X);
                if(hEditWnd > 0)
                {
                    SetWindowCaption(hEditWnd, sc);
                    InvalidateRect(hEditWnd, 0, TRUE);
                }
	            InvalidateRect(hWnd, &rect, TRUE);
	        }
	    }
	    break;
	case ID_RGHT:
	    {
            RECT rect;
            GetFlwRect(hWnd, &rect);
            WND_EXTRA_DATA data;
            data.value = GetWindowAdditionalData(hWnd);
            if(data.pwnd_flower)
            {
                ushort num = GET_RECT_WIDTH(rect) / data.pwnd_flower->zoom;
                ushort nFlwWidth = GetFlowerWidth(g_knit_data);
                data.pwnd_flower->l += num;
                if(data.pwnd_flower->l + num > nFlwWidth)
                {
                    data.pwnd_flower->l = nFlwWidth - num;
                }
                data.pwnd_flower->x += num;
                if(data.pwnd_flower->x >= nFlwWidth)
                {
                    data.pwnd_flower->x = nFlwWidth - 1;
                }
                char sc[32] = { 0 };
                sprintf(sc, "%u", data.pwnd_flower->x + 1);
                HWND hEditWnd = GetDlgItem(hWnd, IDC_EDIT_X);
                if(hEditWnd > 0)
                {
                    SetWindowCaption(hEditWnd, sc);
                    InvalidateRect(hEditWnd, 0, TRUE);
                }
                InvalidateRect(hWnd, &rect, TRUE);
            }
        }
	    break;
	case ID_UP:
	    {
	        RECT rect;
	        GetFlwRect(hWnd, &rect);
	        WND_EXTRA_DATA data;
	        data.value = GetWindowAdditionalData(hWnd);
	        if(data.pwnd_flower)
	        {
	            ushort num = GET_RECT_HEIGHT(rect) / data.pwnd_flower->zoom;
	            ushort nFlwHeight = GetFlowerHeight(g_knit_data);
	            data.pwnd_flower->b += num;
	            if(data.pwnd_flower->b > nFlwHeight)
	            {
	                if(nFlwHeight - num > 0)
                    {
                            data.pwnd_flower->b = nFlwHeight - num;
                    }
                    else
                    {
                        data.pwnd_flower->b = 0;
                    }
	            }
	            data.pwnd_flower->y += num;
	            if(data.pwnd_flower->y >= nFlwHeight)
	            {
	                data.pwnd_flower->y = nFlwHeight - 1;
	            }
	            char sc[32] = { 0 };
                sprintf(sc, "%u", data.pwnd_flower->y + 1);
                HWND hEditWnd = GetDlgItem(hWnd, IDC_EDIT_Y);
                if(hEditWnd > 0)
                {
                    SetWindowCaption(hEditWnd, sc);
                    InvalidateRect(hEditWnd, 0, TRUE);
                }
                InvalidateRect(hWnd, &rect, TRUE);
	        }
	    }
	    break;
	case ID_DOWN:
	    {
	        RECT rect;
	        GetFlwRect(hWnd, &rect);
	        WND_EXTRA_DATA data;
	        data.value = GetWindowAdditionalData(hWnd);
	        if(data.pwnd_flower)
	        {
	            ushort num = GET_RECT_HEIGHT(rect) / data.pwnd_flower->zoom;
	            if(data.pwnd_flower->b < num)
	            {
	                data.pwnd_flower->b = 0;
	            }
	            else
	            {
	                data.pwnd_flower->b -= num;
	            }
	            if(data.pwnd_flower->y < num)
	            {
	                data.pwnd_flower->y = 0;
	            }
	            else
	            {
	                data.pwnd_flower->y -= num;
	            }
	            char sc[32] = { 0 };
                sprintf(sc, "%u", data.pwnd_flower->y + 1);
                HWND hEditWnd = GetDlgItem(hWnd, IDC_EDIT_Y);
                if(hEditWnd > 0)
                {
                    SetWindowCaption(hEditWnd, sc);
                    InvalidateRect(hEditWnd, 0, TRUE);
                }
                InvalidateRect(hWnd, &rect, TRUE);
	        }
	    }
	    break;
	case ID_EDIT:
	    {
	        WND_EXTRA_DATA data;
	        data.value = GetWindowAdditionalData(hWnd);
	        RECT rect;
	        uchar code = 0;
	        if(data.pwnd_flower)
	        {
	            ushort x = data.pwnd_flower->x;
	            ushort y = data.pwnd_flower->y;
	            code = GetFlowerCode(g_knit_data, x, y);
	            FlwToScreen(hWnd, &x, &y);
	            rect.left = x - data.pwnd_flower->zoom;
	            rect.left = __max(0, rect.left);
	            rect.right = x + data.pwnd_flower->zoom;
	            rect.right = __min(rect.right, CX_SCREEN);
	            rect.top = y - data.pwnd_flower->zoom;
	            rect.top = __max(0, rect.top);
	            rect.bottom = y + data.pwnd_flower->zoom;
	            rect.bottom = __min(rect.bottom, CY_SCREEN);
	        }
	        else
	        {
	            rect.left = 400;
	            rect.top = 300;
	            rect.right = 420;
	            rect.bottom = 320;
	        }
	        CreateDatWindow(hWnd, rect, code);
	    }
	    break;
	case ID_ZOOM:
	    {
	        OnZoom(hWnd);
	    }
	    break;
	}
}
/*
 *
 */
static void OnKeyDown(HWND hWnd, uint key)
{
	if(key == SCANCODE_ESCAPE)
	{
		OnBtnCmd(hWnd, ID_ESC);
	}
	else if(key == SCANCODE_CURSORBLOCKLEFT)
	{
	    DecX(hWnd, 1);
	}
	else if(key == SCANCODE_CURSORBLOCKRIGHT)
	{
	    AddX(hWnd, 1);
	}
	else if(key == SCANCODE_CURSORBLOCKUP)
	{
	    AddY(hWnd, 1);
	}
	else if(key == SCANCODE_CURSORBLOCKDOWN)
	{
	    DecY(hWnd, 1);
	}
	else if(key == SCANCODE_F2)
	{
	    OnBtnCmd(hWnd, ID_GOTO_LINE);
	}
	else if(key == SCANCODE_F3)
	{
	    OnBtnCmd(hWnd, ID_START_LINE);
	}
	else if(key == SCANCODE_F4)
	{
	    OnBtnCmd(hWnd, ID_STOP_LINE);
	}
	else if(key == SCANCODE_F5)
	{
	    OnBtnCmd(hWnd, ID_LEFT);
	}
	else if(key == SCANCODE_F6)
	{
	    OnBtnCmd(hWnd, ID_RGHT);
	}
	else if(key == SCANCODE_F8)
	{
	    OnBtnCmd(hWnd, ID_ZOOM);
	}
	else if(key == SCANCODE_PAGEUP)
	{
	    OnBtnCmd(hWnd, ID_UP);
	}
	else if(key == SCANCODE_PAGEDOWN)
	{
	    OnBtnCmd(hWnd, ID_DOWN);
	}
	else if(key == SCANCODE_ENTER)
	{
	    OnBtnCmd(hWnd, ID_EDIT);
	}
}
/*
 *
 */
static void OnLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
    ushort x = lParam & 0xFFFF;
    ushort y = lParam >> 16;
    RECT rect;
    GetFlwRect(hWnd, &rect);
    WND_EXTRA_DATA data;
    data.value = GetWindowAdditionalData(hWnd);
    if(PtInRect(&rect, x, y))
    {
        ushort width = GetFlowerWidth(g_knit_data);
        ushort height = GetFlowerHeight(g_knit_data);
        if(data.pwnd_flower && width && height)
        {
            ScreenToFlw(hWnd, &x, &y);
            data.pwnd_flower->x = x;
            data.pwnd_flower->y = y;
            char sc[32] = { 0 };
            sprintf(sc, "%u", data.pwnd_flower->x + 1);
            HWND hEditWnd = GetDlgItem(hWnd, IDC_EDIT_X);
            if(hEditWnd > 0)
            {
                SetWindowCaption(hEditWnd, sc);
                InvalidateRect(hEditWnd, 0, TRUE);
            }
            sprintf(sc, "%u", data.pwnd_flower->y + 1);
            hEditWnd = GetDlgItem(hWnd, IDC_EDIT_Y);
            if(hEditWnd > 0)
            {
                SetWindowCaption(hEditWnd, sc);
                InvalidateRect(hEditWnd, 0, TRUE);
            }
            FlushCntInfo(hWnd);
        }
    }
}
/*
 *
 */
static void ZoomIn(uchar *pDes, ushort wDes, ushort hDes, uchar *pSrc, ushort wSrc, ushort hSrc)
{
    int h, w;
    float zoom = __max(wSrc / (float)wDes, hSrc / (float)hDes);
    for(h = 0; h < hDes; ++h)
    {
        int hTmp = h * zoom;
        if(hTmp >= hSrc)
        {
            break;
        }
        for(w = 0; w < wDes; ++w)
        {
            int wTmp = w * zoom;
            if(wTmp >= wSrc)
            {
                break;
            }
            pDes[h * wDes + w] = pSrc[hTmp * wSrc + wTmp];
        }
    }
}
/*
 *
 */
static void DrawPoint(HDC hdc,
                      RECT rctFlw,
                      uchar *data,
                      ushort nFlwWidth,
                      ushort nFlwHeight,
                      ushort l,
                      ushort b,
                      uchar zoom)
{
    int nWidth = GET_RECT_WIDTH(rctFlw);
    int nHeight = GET_RECT_HEIGHT(rctFlw);
    BITMAP *p = (BITMAP*) calloc(1, sizeof(BITMAP));
    p->bmWidth = nWidth;
    p->bmHeight = nHeight;
    p->bmBytesPerPixel = 2;
    p->bmBitsPerPixel = 16;
    p->bmPitch = (nWidth * p->bmBytesPerPixel + 3) / 4 * 4;
    p->bmBits = calloc(1, p->bmPitch * nHeight);
    uchar *ptmp = NULL;
    if(data)
    {
        int s = (CELL_FLW_BMP - zoom) / 2;
#if 1
        if(zoom == 1 && (nFlwWidth > nWidth || nFlwHeight > nHeight))
        {
            ptmp = calloc(nHeight, nWidth);
            ZoomIn(ptmp, nWidth, nHeight, data, nFlwWidth, nFlwHeight);
            nFlwWidth = nWidth;
            nFlwHeight = nHeight;
            data = ptmp;
            s = 0;
        }
#endif
        int h, w, z, t;
        for(h = 0; h < __min(nHeight / zoom, nFlwHeight); ++h)
        {
            for(w = 0; w < __min(nWidth / zoom, nFlwWidth); ++w)
            {
                BYTE nColor = data[nFlwWidth * (b + h) + l + w];
                for(z = 0; z < zoom; ++z)
                {
                    int nSrc = g_bmp[BMP_FLW].bmPitch * (s + z) + (nColor
                            * CELL_FLW_BMP + s) * 2;
                    BYTE *q = &((BYTE*) g_bmp[BMP_FLW].bmBits)[nSrc];
                    int nDes = p->bmPitch * (nHeight - 1 - (h + 1) * zoom + 1
                            + z) + (w * zoom) * 2;
                    BYTE *k = &((BYTE*) p->bmBits)[nDes];
                    for(t = 0; t < zoom; ++t)
                    {
                        ((ushort*) k)[t] = ((ushort*) q)[t];
                    }
                }
            }
        }
    }
    //
    FillBoxWithBitmapPart(hdc, rctFlw.left, rctFlw.top, nWidth, nHeight, 0, 0, p, 0, 0);
    free(p->bmBits);
    free(p);
    FREE(ptmp);
}
/*
 *
 */
static int FlowerWinProc(HWND hWnd, int message, WPARAM wParam, LPARAM lParam)
{
	switch(message)
    {
    case MSG_CREATE:
        {
        	CreateFlowerInterface(hWnd);
        }
        break;
    case MSG_PAINT:
        {
            RECT rctFlw;
            GetFlwRect(hWnd, &rctFlw);
            HDC hdc = GetClientDC(hWnd);
            WND_EXTRA_DATA wnd;
            wnd.value = GetWindowAdditionalData(hWnd);
            BYTE zoom = 10;
            ushort l = 0, b = 0;
            if(wnd.pwnd_flower)
            {
                l = wnd.pwnd_flower->l;
                b = wnd.pwnd_flower->b;
                zoom = wnd.pwnd_flower->zoom;
            }
            BYTE *data = GetFlowerData(g_knit_data);
            ushort nFlwWidth = GetFlowerWidth(g_knit_data);
            ushort nFlwHeight = GetFlowerHeight(g_knit_data);
            DrawPoint(hdc, rctFlw, data, nFlwWidth, nFlwHeight, l, b, zoom);
            if(wnd.pwnd_flower->popt && nFlwHeight > 0)
            {
                nFlwWidth = 5;
                data = calloc(1, nFlwWidth * nFlwHeight);
                int h, w;
                for(h = 0; h < nFlwHeight; ++h)
                {
                    for(w = 0; w < nFlwWidth; ++w)
                    {
                        data[nFlwWidth * h + w] = wnd.pwnd_flower->popt[h].all.data[w];
                    }
                }
                rctFlw.left = rctFlw.right + 15;
                rctFlw.right = rctFlw.left + 50;
                DrawPoint(hdc, rctFlw, data, nFlwWidth, nFlwHeight, 0, b, zoom);
                free(data);
            }

            RECT rect;
            uchar code = 0;
            if(wnd.pwnd_flower)
            {
                ushort x = wnd.pwnd_flower->x;
                ushort y = wnd.pwnd_flower->y;
                code = GetFlowerCode(g_knit_data, x, y);
                FlwToScreen(hWnd, &x, &y);
                rect.left = x;
                rect.left = __max(0, rect.left);
                rect.right = x + wnd.pwnd_flower->zoom;
                rect.right = __min(rect.right, CX_SCREEN);
                rect.top = y - wnd.pwnd_flower->zoom;
                rect.top = __max(0, rect.top);
                rect.bottom = y;
                rect.bottom = __min(rect.bottom, CY_SCREEN);

                HDC hdc = GetClientDC(hWnd);
                int width = GET_RECT_WIDTH(rect);
                int height = GET_RECT_HEIGHT(rect);
                FillBoxWithBitmapPart(hdc, rect.left, rect.top, width, height,0, 0,&g_bmp[BMP_FLW_FCS], (code) *10, 0);
            }

            ReleaseDC(hdc);
        }
        break;
    case MSG_CLOSE:
        {
            DestroyMainWindow(hWnd);
            MainWindowCleanup(hWnd);
        }
        return 0;
    case MSG_DESTROY:
        {
            ShowWindow(hWnd, SW_HIDE);
            DestroyAllControls(hWnd);
            WND_EXTRA_DATA data;
            data.value = GetWindowAdditionalData(hWnd);
            if(data.pwnd_flower)
            {
                if(data.pwnd_flower->popt)
                {
                    free(data.pwnd_flower->popt);
                }
                free(data.pwnd_flower);
                SetWindowAdditionalData(hWnd, 0);
            }
        }
        break;
    case MSG_KEYDOWN:
    	{
    	    OnKeyDown(hWnd, wParam);
    	}
        return 0;
    case MSG_ERASEBKGND:
        {
            HDC hdc = GetClientDC(hWnd);
            RECT rect;
            if(lParam)
            {
                memcpy(&rect, (RECT*) lParam, sizeof(RECT));
            }
            else
            {
                GetClientRect(hWnd, &rect);
            }
            int width = GET_RECT_WIDTH(rect);
            int height = GET_RECT_HEIGHT(rect);
            SetBrushColor(hdc, COLOR_HQ_BLACK(hdc));
            FillBox(hdc, rect.left, rect.top, width, height);
            ReleaseDC(hdc);
        }
    	return 0;
    case MSG_COMMAND:
        {
        	OnBtnCmd(hWnd, LOWORD(wParam));
        }
    	return 0;
    case MSG_LBUTTONDOWN:
        {
            OnLButtonDown(hWnd, wParam, lParam);
        }
        break;
    case MSG_GOTO_LINE:
        {
            ushort line = wParam;
            if(line > 0 && line <= GetFlowerHeight(g_knit_data))
            {
                WND_EXTRA_DATA data;
                data.value = GetWindowAdditionalData(hWnd);
                if(data.pwnd_flower)
                {
                    if(data.pwnd_flower->y + 1 != line)
                    {
                        int n = line - (data.pwnd_flower->y + 1);
                        if(n < 0)
                        {
                            DecY(hWnd, -n);
                        }
                        else
                        {
                            AddY(hWnd, n);
                        }
                    }
                }
            }
        }
        break;
    case MSG_IDLE:
        {
            static uchar even = 0;
            even = !even;
            RECT rect;
            GetFlwRect(hWnd, &rect);
            WND_EXTRA_DATA data;
            data.value = GetWindowAdditionalData(hWnd);
            ushort x = data.pwnd_flower->x;
            ushort y = data.pwnd_flower->y;
            FlwToScreen(hWnd, &x, &y);
            rect.left = x;
            rect.right = rect.left + data.pwnd_flower->zoom;
            rect.bottom = y;
            rect.top = rect.bottom - data.pwnd_flower->zoom;
            HDC hdc = GetClientDC(hWnd);
            if(even)
            {
                SetBrushColor(hdc, COLOR_HQ_WHITE(hdc));
                FillBox(hdc, rect.left, rect.top, data.pwnd_flower->zoom,
                        data.pwnd_flower->zoom);
            }
            else
            {
                InvalidateRect(hWnd, &rect, FALSE);
            }
            //frame
            RECT rctFlw;
            GetFlwRect(hWnd, &rctFlw);
            SetPenColor(hdc, (RGB2Pixel(hdc, 0x00, 0x00, 0x80)));
            Rectangle(hdc, rctFlw.left - 5, rctFlw.top - 5, rctFlw.right + 5,
                    rctFlw.bottom + 5);
            Rectangle(hdc, rctFlw.right + 10, rctFlw.top - 5, rctFlw.right + 70,
                                rctFlw.bottom + 5);

            ReleaseDC(hdc);
        }
        break;
    }
    return DefaultMainWinProc(hWnd, message, wParam, lParam);
}
/*
 *
 */
HWND CreateFlowerWindow(HWND hHosting)
{
    WND_EXTRA_DATA data;
    data.pwnd_flower = calloc(1, sizeof(FLOWER_WND));
    data.pwnd_flower->zoom = 10;
    GetCntInfo(&data.pwnd_flower->cnt_info, 1);
    ushort flw_height = GetFlowerHeight(g_knit_data);
    if(flw_height)
    {
        data.pwnd_flower->popt = calloc(flw_height, sizeof(OPT_FUN));
        GetOptInfo(data.pwnd_flower->popt);
    }

    MAINWINCREATE CreateInfo;
    CreateInfo.dwStyle = WS_VISIBLE;
    CreateInfo.dwExStyle = WS_EX_NONE;
    CreateInfo.spCaption = MW_FLW_BT_CAPTION;
    CreateInfo.hMenu = 0;
    CreateInfo.hCursor = GetSystemCursor(0);
    CreateInfo.hIcon = 0;
    CreateInfo.MainWindowProc = FlowerWinProc;
    CreateInfo.lx = 0;
    CreateInfo.ty = 0;
    CreateInfo.rx = CX_SCREEN;
    CreateInfo.by = CY_SCREEN;
    CreateInfo.iBkColor = COLOR_lightwhite;
    CreateInfo.dwAddData = data.value;
    CreateInfo.hHosting = hHosting;
    HWND hWnd = CreateMainWindow(&CreateInfo);
    if(hWnd != HWND_INVALID)
    {
    	ShowWindow(hWnd, SW_SHOWNORMAL);
    }
    return hWnd;
}
